<?php
/*
 * -File        queryhandler.php - Wed Aug  7 14:03:21 MST 2002
 * -License     LGPL (http://www.gnu.org/copyleft/lesser.html)
 * -Copyright   2002, Nexista
 * -Author      joshua savage <js@nexista.com>
 */

/**
 * @package     Nexista
 * @subpackage  Handlers
 * @author      Joshua Savage <js@nexista.com>
 */
 
/**
 * This class is the query handler.
 * It uses an php query and retrieves from or sends data to
 * a datasource (sql,ldap,etc)
 * Note that LOB suport is not in yet
 *
 * @package     Nexista
 * @subpackage  Handlers
 */
class SqlHandler
{

    /**
     * Singleton instance
     *
     * @var     string
     */
     
    private static $instance;
    
    
    /**
     * Processing flag
     *
     * @var     boolean
     * @see     Sqlhandler::setInactive
     */
     
    private $active = true;
    
    
    /**
     * Name of query
     *
     * This name is set in the query file under
     * <query name="..."> and is used to reference
     * The query results in Flow (i.e. //queryname/datavar)
     *
     * @var     string
     */

    private $queryName;
    
    
    /**
     * The datasource connection name
     *
     * @var     string
     */
    private $connectionName;

        
    /**
     * Array containing all the current query info
     *
     * @var     array
     */
    private $query;

    
    /**
     * Datasource handler type
     *
     * This points to the correct datasource handler
     * such as sql, ldap, etc...
     *
     * @var     string
     */

    private $datasourceHandler;
    
   
    /**
     * Reference to the datasource object (sql,ldap,csv etc)
     *
     * @var     string
     */
    private $datasource;


    /**
     * Query loop index
     *
     * This variable determines whether the query
     * will be looped/repeated. This variable accepts either
     * an integer (loop count) or a flow value (will repeat
     * for every instance of this value).
     * This allows a query to be repeated multiple times in a row.
     * Query variables can be changed by setting the 'array' 
     * parameter in the relevant setParam() call. The loop
     * will repeat and use the values of these array params sequentially.
     *
     * @var     string
     */

    private $queryLoop = 1;
 
    
    /**
     * Sets query name
     *
     * This name is used by Flow to name each retrieved element
     *
     * @param   string      the name of the query
     */
     
    static public function setName($name)
    {
        $me = SqlHandler::singleton();
        $me->queryName = $name;
    
    }
    
    
    /**
     * Sets query connection name
     *
     * The connection name should refer to a valid datasource setting
     * in the site configuration files.
     *
     * @param   string      the name of the connection
     */
     
    static public function setConnection($name)
    {
        $me = SqlHandler::singleton();
        
        $me->connectionName = $name;
       
      
    
    }
    
    
    /**
     * Turns off the query processing.
     *
     * This is used in som instances where it is desired
     * that the query process should not be activated.
     * i.e. the query file results in a logic that specifies
     * that no query should in fact be called. Calling this method
     * will prevent the query process from running a useless or empty query
     *
     * @param   boolean      true or false
     */
     
    static public function setInactive()
    {
        $me = SqlHandler::singleton();
        $me->active = false;
    
    }
    
    
    
    /**
     * Sets query loop
     *
     * @param   integer      the number of times to loop query
     */
     
    static public function setLoop($val)
    {
        $me = SqlHandler::singleton();
        $me->queryLoop = $val;
    
    }
    
    
    /**
     * Sets a query parameter
     *
     *
     * @param   string      value (i.e. flow query) of param
     * @param   string      type of param (text,integer,...)
     * @param   string      default value
     * @param   boolean     process as array?
     * @return  boolean     success
     */
     
    static public function setParam($name, $type = 'text', $default = null, $array = false)
    {
    
        $me =  SqlHandler::singleton();
        $key = count($me->query['params']);
        
        $me->query['params'][$key]['name'] = !(empty($name) AND $array) ?  $name : false;
                    
        $me->query['params'][$key]['array'] = $array ?  $name : false;
                                            
        $me->query['params'][$key]['default'] = (!empty($default) OR $default === '0')?  $default : 'NULL';           
        $me->query['params'][$key]['type'] = !empty($type) ?  $type : false;
        
        return true;
      
    }
    
    /**
     * Sets the sql for the query
     *
     *
     * @param   string      sql 
     * @return  boolean     success
     */
     
    static public function setQuery($sql)
    {
        $me =  SqlHandler::singleton();
        $me->query['sql'] = $sql;      
        return true;
    }
    
    
    /**
     * Sets the paging limits
     *
     *
     * @param   integer     first item 
     * @param   integer     item limit
     * @return  boolean     success
     */
     
    static public function setPaging($first, $limit)
    {
        $me =  SqlHandler::singleton();
        $me->query['rows']['first'] = $first;
        $me->query['rows']['limit'] = $limit;
    }
    
    
    /**
     * Loads datasource handler
     *
     * Loads correct module based on
     * $this->datasourceHandler value and
     * instantiates it.
     *
     * @param   array       module parameters
     */

    private function loadModule(&$params)
    {

        //load the datasource module file based on type
        require_once(NX_PATH_DATASOURCES . $this->datasourceHandler . "datasource.php");

        $class = trim(ucfirst($this->datasourceHandler)) . "Datasource";
        $this->datasource = new $class($params);
        return true;


    }
    
    /**
     * Accepts an xml based query and processes it according
     * to passed criteria
     *
     * @return  boolean     success
     */

    public function process()
    {            
        //maybe we do not need to process?
        if(!$this->active)
            return true;
            
        //get the datasource type (sql,ldap)
        $this->getDatasource($this->connectionName, $params);
       
        //instantiate the dataource handler
        $this->loadModule($params);
        
        $this->datasource->setConnection();

        $this->datasource->execQuery( $this->query,  $this->queryName,  $this->queryLoop);
        $this->datasource->db->CloseSetup();
       
        //TODO error message in gate
        return true;
    }

   function clean()
   {
    
        
        $this->queryLoop = 1;
        
        unset($this->datasource);
        unset($this->query);
        unset($this->queryName);        
        unset($this->connectionName);
        unset($this->datasourceHandler);
        
        
   }
    
    /**
     * Retrieves database info from global.xml file based
     * on query type
     *
     * @param   string      datasource name - must match one on global.xml
     * @param   array       database parameters (username, host, password, etc)
     */

    private function getDatasource($name, &$datasource)
    {
        $datasource = Config::getSection('datasource',$name);

        //Debug::dump($datasource);

        //Developer note: This is where you set what Datasource handler you would
        //like to use based on type (<type> in global.xml)
        switch($datasource['type'])
        {
            case 'mysql':
            case 'ibase':
            case 'ifx':
            case 'mssql':
            case 'msql':
            case 'mysql':
            case 'odbc':
            case 'oci':
            case 'pgsql':
                $this->datasourceHandler = 'sql'; //metabase
                break;
            default:
                Error::init($type.' datasource type is not supported', NX_ERROR_WARNING);
                return false;
                break;
        }

        return true;
    }

    
    public static function singleton()
    {
        if(!isset(self::$instance)) 
        {
            self::$instance = new SqlHandler();
        }
        return self::$instance;
}
  

} //end class
?>
